import axios from 'axios'
import router from '../router'
import qs from 'qs'
import { Message,Loading } from 'element-ui'
import { getToken,removeToken,getRequireId } from './permission'
import { repeatSubmit,loadingEffect,routerPath,headers } from '@/config/setting'

// 正在进行中的请求列表
let reqList = []

/**
 * 阻止重复请求
 * @param {array} reqList - 请求缓存列表
 * @param {string} url - 当前请求地址
 * @param {function} cancel - 请求中断函数
 * @param {string} errorMessage - 请求中断时需要显示的错误信息
 */
const stopRepeatRequest = function (reqList, url, cancel, errorMessage) {
	const errorMsg = errorMessage || ''
	for (let i = 0; i < reqList.length; i++) {
		if (reqList[i] === url) {
			cancel(errorMsg)
			return
		}
	}
	reqList.push(url)
}

/**
 * 允许某个请求可以继续进行
 * @param {array} reqList 全部请求列表
 * @param {string} url 请求地址
 */
const allowRequest = function (reqList, url) {
	for (let i = 0; i < reqList.length; i++) {
		if (reqList[i] === url) {
			reqList.splice(i, 1)
			break
		}
	}
}

let loading; // 声明变量

// 请求地址
if (process.env.NODE_ENV == 'development') {
	axios.defaults.baseURL = process.env.BASE_API;
} else if (process.env.NODE_ENV == 'debug') {
	axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV == 'production') {
	axios.defaults.baseURL = process.env.BASE_API;
};

// 请求超时时间
axios.defaults.timeout = 30000;

// 请求头
axios.defaults.headers.post[headers.contentType.name] = headers.contentType.value;

// 请求拦截器
axios.interceptors.request.use(config => {
	if (loadingEffect.enabled) {
		loading = Loading.service({
			lock: true,
			text: loadingEffect.text,
			background: "rgba(0, 0, 0, 0)"
		})
	}
	if (getToken()) {
		config.headers[headers.tokenName] = getToken();
		if (config.method === "post" && getRequireId()) {
			if (!config.data instanceof FormData) {
				let data = qs.parse(config.data);
				config.data = qs.stringify({
					inst_id: getRequireId(),
					...data
				});
			}
		}else if (config.method === "get" && getRequireId()) {
			config.params = {
				inst_id: getRequireId(),
				...config.params
			}
		}
	}
	if (repeatSubmit.enabled) {
		let cancel
		// 设置cancelToken对象
		config.cancelToken = new axios.CancelToken(function(c) {
			cancel = c
		})
		// 阻止重复请求。当上个请求未完成时，相同的请求不会进行
		stopRepeatRequest(reqList, config.url, cancel, `请勿频繁操作，请稍后再试。`)
	}
	return config;
}, error => {
	if (loadingEffect.enabled) {
		loading.close();
	}
	return Promise.reject(error);
});

// 响应拦截器
axios.interceptors.response.use(
response => {
	if (loadingEffect.enabled) {
		loading.close();
	}
	if (repeatSubmit.enabled) {
		// 增加延迟，相同请求不得在短时间内重复发送
		setTimeout(() => {
			allowRequest(reqList, response.config.url)
		}, repeatSubmit.duration)
	}
	return response;
}, error => {
	if (loadingEffect.enabled) {
		loading.close();
	}
	if (error && error.response) {
		switch (error.response.status) {
			case 401:
				removeToken();
				router.replace(
					{ path: routerPath.login.path }, 
					onComplete => {}, onAbort => {}
				)
				error.message = error.response.data.msg
				break;
			case 404:
				error.message = '请求错误,未找到该资源'
				break;
			default:
				error.message = `连接错误${error.response.status}`
		}
	}
	Message.error(error.message)
	if (repeatSubmit.enabled) {
		if (axios.isCancel(error)) {
			console.log(error.message);
		} else {
			// 增加延迟，相同请求不得在短时间内重复发送
			setTimeout(() => {
				allowRequest(reqList, error.config.url)
			}, repeatSubmit.duration)
		}
	}
	return Promise.reject(error.response.data);
})

/** 
 * get方法，对应get请求 
 * @param {String} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */
export function get(url, params){    
    return new Promise((resolve, reject) =>{        
        axios.get(url, {            
            params: params
        })        
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}

/** 
 * post方法，对应post请求 
 * @param {String} url [请求的url地址] 
 * @param {Object} params [请求时携带的参数] 
 */
export function post(url, params) {    
    return new Promise((resolve, reject) => {         
        axios.post(url, qs.stringify(params))
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}

/**
 * 文件上传
 * @param {Object} url
 * @param {Object} params
 */
export function upload(url, params) {
    return new Promise((resolve, reject) => {
        axios.post(url, params, {headers: {'Content-Type': 'multipart/form-data'}})
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}
